 /*****************************************************************************
 *  This file is part of the OpenDomo project.
 *  Copyright(C) 2011 OpenDomo Services SL
 *  
 *  Daniel Lerch Hostalot <dlerch@opendomo.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/


// ----------------------------------------------------------------------------
// author: Daniel Lerch <dlerch@gmail.com>, http://www.opendomo.com
// date: October 2008
//
// CHANGES:
//	14-10-2008	dlerch: Read file content (need POSIX).
//	17-10-2008	dlerch: string manipulation: trim, replace
// ----------------------------------------------------------------------------




#ifndef __STRING_H__
#define __STRING_H__


/* HEADERS */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<ctype.h>
#include<assert.h>


/**
 * STRING_CREATE_FROM_STR: Declare 'varname', allocate memory and assign str.
 *
 * @param varname: variable name.
 * @param str: string to assign.
 */
#define STRING_CREATE_FROM_STR(varname, str) \
	char *varname = malloc(strlen(str)+1); \
	strncpy(varname, str, (strlen(str))); \
	varname[strlen(str)]=0;

/**
 * STRING_CREATE_FROM_FILE: Declare 'varname', allocate memory and assign str
 * from file.
 *
 * @param varname: variable name.
 * @param file: file to read.
 */
#define STRING_CREATE_FROM_FILE(varname, filename) \
	char *varname = calloc(1,1); \
	struct stat statbuf; \
	int f; \
	if((f=open(filename, O_RDONLY))>=0) \
	{\
		if(fstat(f,&statbuf)>=0) \
		{ \
			char *p = NULL; \
			if((p=mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,f,0))!=(caddr_t)-1)\
			{ \
				varname = realloc(varname, strlen(p)+1); \
				strncpy(varname, p, (strlen(p))); \
				varname[strlen(p)]=0; \
				munmap(0, statbuf.st_size); \
			} \
		} \
	}



/**
 * STRING_SIZE: strlen() wrapper. Returns file lenght.
 *
 * @param varname: varaible name.
 * @return size_t: string's lenght.
 */
#define STRING_SIZE(varname) strlen(varname)



/**
 * STRING_ASSIGN_FROM_STR: reallocate memory and assign str.
 *
 * @param varname: variable name.
 * @param str: string to assign.
 */
#define STRING_ASSIGN_FROM_STR(varname, str) \
	if(varname) free(varname); \
	varname = malloc(strlen(str)+1); \
	strncpy(varname, str, (strlen(str))); \
	varname[strlen(str)]=0;


/**
 * STRING_APPEND_STR: reallocate memory and append str.
 *
 * @param varname: variable name.
 * @param str: string to append.
 */
#define STRING_APPEND_STR(varname, str) \
   { \
      char *ptr = malloc(strlen(str)+strlen(varname)+1); \
      snprintf(ptr, strlen(str)+strlen(varname)+1, "%s%s", varname, str); \
	   if(varname) free(varname); \
	   varname = ptr; \
   } 




/**
 * STRING_ASSIGN_FROM_FILE: reallocate 'varname' memory and assign str
 * from file.
 *
 * @param varname: variable name.
 * @param file: file to read.
 */
#define STRING_ASSIGN_FROM_FILE(varname, str) \
	if(varname) free(varname); \
	varname = calloc(1,1); \
	char *p = NULL; \
	struct stat statbuf; \
	int f; \
	if((f=open(filename, O_RDONLY))>=0) \
	{\
		if(fstat(f,&statbuf)>=0) \
		{ \
			if((p=mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,f,0))!=(caddr_t)-1)\
			{ \
				varname = realloc(varname, strlen(p)+1); \
				strncpy(varname, p, (strlen(p))); \
				varname[strlen(p)]=0; \
				munmap(0, statbuf.st_size); \
			} \
		} \
	}



/**
 * STRING_TRIM: remove spaces from the begining and the end.
 *
 * @param varname: variable name.
 */
#define STRING_TRIM(varname) \
	{ \
		char __string[strlen(varname)+1]; \
		strncpy(__string, varname, sizeof(__string)); \
		__string[sizeof(__string)-1]=0; \
		char *__ptr = __string; \
		while(isspace(*__ptr)) __ptr++; \
		strncpy(varname, __ptr, strlen(varname)); \
		varname[strlen(varname)] = 0; \
		__ptr = varname+strlen(varname)-1; \
		while(isspace(*__ptr)) __ptr--; \
		*(__ptr+1)=0; \
	}


/**
 * STRING_REPLACE: string replacement
 *
 * @param varname: string variable name.
 * @param original: old string
 * @param replacement: new string
 */
#define STRING_REPLACE(varname, original, replacement) \
	{ \
		int n_src=0; \
		char *__ptr = varname; \
		char *__ptr2 = varname; \
		while((__ptr=strstr(__ptr, original))) { n_src++; __ptr++; } \
		int new_size = strlen(varname) + \
			n_src*(strlen(replacement)-strlen(original)); \
		char __string[new_size+1]; \
		__string[0]=0; \
		__ptr = varname; \
		while((__ptr=strstr(__ptr, original))) \
		{ \
			int len = __ptr-__ptr2; \
			strncat(__string, __ptr2, len); \
			strncat(__string, replacement, sizeof(__string)); \
			__string[sizeof(__string)-1]=0; \
			__ptr2 = __ptr+strlen(original); \
			__ptr  = __ptr+strlen(original); \
		} \
		int len = __ptr-__ptr2; \
		strncat(__string, __ptr2, len); \
		varname = realloc(varname, new_size+1); \
		strncpy(varname, __string, new_size); \
		varname[new_size]=0; \
	}


/**
 * STRING_LPAD: Left padding
 * Note that if varname lenght is bigger than total_len do nothing.
 *
 * @param varname: string variable name.
 * @param padd_char: character used 
 * @param total_len: 
 */
#define STRING_LPAD(varname, padd_char, total_len) \
	if(strlen(varname)<total_len) \
	{ \
		int i; \
		char __string[total_len]; \
		strncpy(__string, varname, sizeof(__string)); \
		__string[sizeof(__string)-1]=0; \
		varname = realloc(varname, total_len+1); \
		for(i=0; i<total_len-strlen(__string); i++) \
			varname[i]=padd_char; \
		varname[i]=0; \
		strncat(varname, __string, total_len); \
		varname[total_len]=0; \
	}

/**
 * STRING_LPAD: Right padding
 * Note that if varname lenght is bigger than total_len do nothing.
 *
 * @param varname: string variable name.
 * @param padd_char: character used 
 * @param total_len: 
 */
#define STRING_RPAD(varname, padd_char, total_len) \
if(strlen(varname)<total_len) \
	{ \
		int i; \
		varname = realloc(varname, total_len+1); \
		for(i=strlen(varname); i<total_len; i++) \
			varname[i]=padd_char; \
		varname[total_len]=0; \
	}




/**
 * STRING_DESTROY: Free string's memory.
 *
 * @param varname: variable name.
 */
#define STRING_DESTROY(varname) if(varname) free(varname);


#endif
